home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok10.lha / SuperLists1.3 / SuperLists.dok < prev    next >
Text File  |  1993-08-15  |  17KB  |  350 lines

  1. Dokumentation zu "SuperLists" Version 1.3
  2. Autor: Nicolas Benezan, Postwiesenstr.2, 7000 Stuttgart 60
  3. Unterstützung von Text-Listen mit Scroll-Gadgets
  4.  
  5. Einleitung
  6. ----------
  7. SuperLists vereinfacht die Programmiering von Scrollfähigen Textlisten,
  8. wie sie z.B. in Auswahlrequestern Verwendung finden. Es werden 
  9. Proportional- und Einzelschrittgadgets in X- und/oder Y-Richtung
  10. unterstützt.
  11. Inzwischen gibt es auch das Modul FileRequest (mit Demo), das ein gutes
  12. Beispiel für die Verwendung von SuperLists ist.
  13.  
  14. Neu: Version 1.3
  15. ----------------
  16. Bei der neuen Version kann auf Wunsch das horizontale Scrollgadget
  17. weggelassen werden. Es ist auch möglich, mit Hilfe der Prozedur-
  18. variablen AllocProc und DeallocProc eine eigene Speicherverwaltung 
  19. einzubinden. Darüberhinaus ist man jetzt nicht mehr an den Entry-
  20. RECORD gebunden sondern kann sich mit 
  21.  
  22. TYPE    ExtEntry=RECORD
  23.            Node:MinEntry;
  24.            Data:IrgendeinTyp;
  25.                  END;
  26.  
  27. eigene Eintragstypen konstruieren.
  28. Neu ist auch die Prozedur ClearList().
  29.  
  30.  
  31. So wird's gemacht
  32. -----------------
  33. Bevor man eine SuperList erzeugt, sollte man sich über folgendes im 
  34. Klaren sein:
  35. * In welchem Window(-rastport) oder Requester(-rastport) soll die
  36.   Liste angezeigt werden
  37. * Welche Hintergrundfarbe hat die Liste
  38. * Wie sollen die Proportionalgadgets für vertikales und (falls
  39.   erwünscht) horizontales Srolling aussehen
  40. * Wo und wie groß soll die Liste im Window (Requester) angezeigt
  41.   werden
  42. * Welche Daten hat der zu dem verwendeten RastPort gehörige
  43.   Zeichensatz (Achtung, es darf keine Proportionalschrift sein)
  44. * Welcher Ausschnitt soll voreinstellungsgemäß angezeigt werden
  45. Bei der Version kann nun auch gewählt werden, ob die Liste nur vertikal
  46. oder vertikal und horizontal gescrollt werden soll.
  47.  
  48. Erzeugen der Scrollgadgets
  49. --------------------------
  50. Jede SuperList benötigt ein oder zwei Proportionalgadgets, eines für 
  51. das vertikale Scrolling und optional ein zweites für die horizontale 
  52. Richtung. Diese Gadgets müssen erzeugt werden, bevor die Liste initiali-
  53. siert wird. Es wird hier auf eine Beschreibung, wie dies geschieht, 
  54. verzichtet. Dies kann man zB. im "Intuition Reference Manual" nachlesen.
  55.  
  56. Initialisieren der Liste
  57. ------------------------
  58. Eine SuperList besteht aus einem Listenkopf (SuperList-RECORD) und null
  59. oder mehreren Einträgen (Entry-RECORDs). Der Listenkopf enthält Parameter,
  60. die das Aussehen der Liste beschreiben, und solche, die vom SuperList-
  61. Modul zur Verwaltung der Liste benötigt werden, sowie eine Exec.List zur
  62. Verwaltung der Einträge. Ein Eintrag enthält einen Exec.Node zur 
  63. Verknüpfung der Einträge untereinander und den eigentlichen Text (in 
  64. Entry.node.name) sowie Parameter, die das Aussehen des Textes beschreiben
  65. (Farbe, DrawMode).
  66. Bevor die Liste das erste mal verwendet werden kann, müssen folgende
  67. Paramter in der SuperList-Struktur initialisiert werden:
  68. * rastPort - Zeiger auf den RastPort des Windows oder Requesters, in
  69.   dem die Liste angezeigt werden soll.
  70. * backPen - Hintergrundfarbe der Liste
  71. * propY - Zeiger auf das Proportionalgadget für vertikales Scrolling
  72. * propX - Zeiger auf das Gadget für horizontales Scrolling falls dies 
  73.   nicht erwünscht ist, sollte PropX auf NIL gesetzt werden
  74. * leftEdge - linker Rand der Listenanzeigefläche relativ zum linken
  75.   Rand des Windows oder Requesters (Einheit: Pixel)
  76. * topEdge - oberer Rand relativ zum Rand des Windows/Requesters
  77. * width - Breite der Anzeigefläche (Einheit: Pixel), muß mindestens so
  78.   groß wie FontXsize+1 sein (s. unten)
  79. * height - Höhe der Anzeigefläche, muß mindestens FontYsize sein
  80. * FontXsize - Breite eines Zeichens in Pixel (kein Proportional- 
  81.   schriftsatz!)
  82. * FontYsize - Höhe einer Textzeile in Pixel(muß nicht unbedingt mit
  83.   der Höhe eines Zeichens übereinstimmen, wenn zB. zusätzlicher    
  84.   Zeilenabstand erwünscht ist)
  85. * FontBaseLine - besagt, auf welcher Höhe die Grundlinie der Zeichen
  86.   innerhalb einer Zeile liegen soll, sollte ungefähr gleich dem    
  87.   baseLine-Paramter des Fonts gesetzt werden
  88. * dispRow - Nummer des ersten Eintrags (Zeile) des zuerst    
  89.   anzuzeigenden Ausschnitts (0 ist der erste Eintrag)
  90. * dispColumn - Nummer der ersten Spalte des Ausschnitts (0 zeigt ab
  91.   der ersten Spalte)
  92.   ist kein horizontales Scrolling vorgesehen, sollte dieses Feld immer     0 
  93.   sein
  94. * Die Exec.List muß initialisiert werden. Dies geschieht am besten mit
  95.   ExecSupport.NewList(ADR(SuperList.list); .
  96. Alle anderen Felder sollten nie verändert werden, sie dienen der internen
  97. Verwaltung. Es ist aber vielleich manchmal interessant, sie zu lesen, 
  98. deshalb hier ihre Bedeutungen:
  99. * rows - Anzahl der vorhandenen Einträge (Zeilen)
  100. * columns - Anzahl der Spalten = Länge des längsten Eintrags (in
  101.   Zeichen, nicht in Pixel), nur bei eingeschltetem horizontalem 
  102.   Scrolling definiert
  103. * topEntry - Zeiger auf den Node des obersten angezeigten Eintrags
  104. * bottomEntry - Zeiger auf den untersten angezeigten Eintrag
  105.   (Vorsicht: Falls keine Einträge vorhanden sind, müssen top- und 
  106.   bottomEntry nicht unbedingt NIL sein. Diese Zeiger sollten möglichst
  107.   nicht für eigene Zwecke verwendet werden.)
  108. * effWidth - Breite der Anzeigefläche in Zeichen (nicht in Pixel)
  109. * effHeight - Höhe in Zeichen
  110. Nachdem alles ordnungsgemäß initialisiert ist, wird RethinkList( 
  111. SuperListPtr, NewList) aufgerufen, wobei SuperListPtr ein Zeiger auf 
  112. den SuperList-RECORD und NewList eine von SuperLists exportierte 
  113. Konstante ist (newList/oldList). Um den aktuellen Ausschnitt der Liste
  114. anzuzeigen, verwendet man RefreshList(SuperListPtr). Man kann die Liste 
  115. jetzt mit den Prozeduren ScrollList, InsertEntry, RemoveEntry, GetEntry,
  116. SetProp, GetProp, ClickRow, MakeEntry, RedrawEntry, RethinkList und 
  117. RefreshList bearbeiten.
  118.  
  119. RefreshList
  120. -----------
  121. Diese Prozedur wird benötigt, um die Paramter zur interenen Verwaltung 
  122. im Listenkopf neu zu berechnen. Normalerweise werden diese beim Aufruf 
  123. von Prozeduren wie zB. InsertEntry automatisch aktualisiert. Es ist 
  124. jedoch manchmal nötig, einige Parameter "von Hand" zu ändern, wenn zB. 
  125. der Benutzer die Windowgröße verändert hat, und sich damit auch die 
  126. Anzeigefläche der Liste verändert. Um das SuperLists-Modul davon in 
  127. Kenntnis zu setzen, daß Parameter verändert wurden, sodaß es seine 
  128. internen Parameter neu be
  129. echnen kann, wird RethinkList verwendet. Der Parameter New (newList 
  130. oder oldList) besagt, inwieweit die Listenparameter rekonstruiert werden
  131. müssen. RethinkList(...,oldList) wird verwendet, wenn die Veränderung nur
  132. die Anzeigefläche betrifft (zB. Höhe, Breite, Zeichensatz usw.). Die 
  133. Ausführungszeit ist im Gegensatz zu RethinkList(...,newList) relativ 
  134. kurz. Bei letzterem wird nämlich die ganze Liste der Einträge durch-
  135. gegangen und Zeilen und Spalten werden neu gezählt. Dies ist notwendig,
  136. wenn die Einträge mit anderen Prozeduren als die von SuperLists 
  137. bearbeitet wurden, sodaß sich die Texte der Einträge verändert haben,
  138. oder Eiträge entfernt oder hinzugefügt wurden. Ein weiterer Fall ist 
  139. das Erzeugen einer neuen Liste (siehe oben) oder ein Spezialfall von 
  140. emoveEntry (siehe dort). Wegen der besonders bei sehr großen Listen 
  141. langen Ausführungszeit sollte RethinkList(...,newList) möglichst 
  142. vermieden werden. Um einen einzelnen Eintrag abzuändern, ist es besser,
  143. ihn mit RemoveEntry zu entfernen und nach der Änderung mit InsertEntry
  144. wieder einzufügen.
  145. Folgende Parameter dürfen verändert werden, ohne daß RethinkList benötigt
  146. wird:
  147. SuperList.backPen, SuperList.FontBaseLine, Entry.frontPen, Entry.backPen,
  148. Entry.drawMode, Entry.userFlags, Entry.userData .
  149. Achtung: Wenn Parameter (außer den oben genannten) einer SuperList-
  150. Struktur "von Hand", also nicht über SuperLists-Prozeduren, verändert 
  151. werden, so darf keine andere SuperLists-Prozedur aufgerufen werden, bevor
  152. nicht RethinkList ausgeführt wurde. Die Prozedur findet sonst ungültige 
  153. Werte vor, was zu einer chaotischen Anzeige und schlimmstenfalls sogar 
  154. zum Systemabsturz führen kann. Falls von mehreren Tasks aus auf eine Liste
  155. zugegriffen wird, muß das Programmstück von der Parameterveränderung bis
  156. RethinkList im Forbidden-Status ablaufen.
  157. RethinkList korrigiert soweit als möglich ungültige Werte. Wenn zB. der
  158. aktuelle Anzeigeauschnitt über das Ende der Liste hinaus positioniert
  159. wurde, so wird der Ausschnitt auf die tiefstmögliche Position gesetzt. 
  160. Diese Gutmütigkeit hat aber ihre Grenzen.
  161. So sollte man zB. keine Zeiger der Exec.List "verbiegen" oder eine
  162. negative Anzeigenbreite einstellen, weil solche "Scherze" meist unvorher-
  163. sehbare Folgen haben.
  164.  
  165. RefreshList
  166. -----------
  167. Wie schon der Name sagt, dient diese Prozedur dem Auffrischen, dh. dem 
  168. Neu-Anzeigen, des sichtbaren Listenausschnitts. Dies wird in drei Fällen
  169. benötigt:
  170. * wenn die Liste zum ersten mal angezeigt werden soll,
  171. * wenn sich die Liste in einem SimpleRefresh-Window befindet und man 
  172.   eine Message vom Typ "refreshWindow" erhält oder
  173. * wenn sich die Größe der Anzeigefläche verändert hat. Es ist auch dann
  174.   ein Auffrischen erforderlich, wenn die Fläche kleiner geworden ist.
  175. Im Fall 1 und 3 ist auch noch zusätzlich SetProp() erforderlich 
  176. (siehe dort).
  177.  
  178. RedrawEntry
  179. -----------
  180. Zeigt einen Eintrag (Zeile) neu an, sofern sich dieser im gerade 
  181. sichtbaren Ausschnitt befindet. Dies ist notwendig, wenn zB. der Text, 
  182. die Farbe oder der DrawModus dieses Eintrags verändert wurde. Falls sich
  183. die Länge des Texts verändert hat muß außerdem RethinkList() aufgerufen
  184. werden (siehe oben). Es ist dabei möglich, vorher einen alternativen 
  185. Zeichensatz (zB. kursiv) zu setzen (mit Graphics.Set- Font() ), um diesen
  186. Eintrag besonders hervorzuheben. Dieser muß (!) aber die gleiche Zeichen-
  187. größe wie der vorher verwendete haben (FontXsize, FontYsize).
  188.  
  189. ScrollList
  190. ----------
  191. wird verwendet, um die Liste Zeichenweise in eine beliebige Richtung zu
  192. scrollen. Dies wird besonders bei Texteditoren benötigt, oder wenn die 
  193. beiden Proportionalscrollgadgets noch mit je zwei Boolgadgets kombiniert 
  194. sind (siehe zB. die kleinen Pfeile in den Ecken der Workbench-Windows). 
  195. Das Scrolling läuft relativ schnell (weil blitterunterstützt) ab, und es 
  196. wird nur der beim Verschieben der BitPlane-Daten freigelegte Abschnitt 
  197. neu gezeichnet. Es wird damit möglich, Texteditoren zu bauen, bei denen 
  198. man nicht ewig warten muß, wenn man sich mit dem Cursor über den 
  199. Windowrand hinausbewegt hat (sowas soll's auch geben!).
  200. Es ist nicht möglich, über das Ende oder vor den Anfang der Liste zu 
  201. scrollen. Dies wird automatisch erkannt und abgefangen.
  202. "Dir" gibt die Richtung an, mit der sich das imaginäre Fenster über die
  203. Liste bewegt. "Left" bedeutet also, die sichtbaren Daten werden 
  204. eigentlich rechtsverschoben, links wird ein Zeichen mehr sichtbar, rechts
  205. verschwindet eins.
  206.  
  207. MakeEntry
  208. ---------
  209. Bevor irgendetwas angezeigt oder gescrollt werden kann, müssen erst 
  210. einmal Einträge in der Liste vorhanden sein. Meistens werden diese 
  211. dynamisch alloziert, was am besten mit der Prozedur MakeEntry geschieht.
  212. Es wird ein Zeiger auf einen auf Null endenden String, Vorder- und 
  213. Hinergrundfarbe und der gewünschte DrawModus übergeben. MakeEntry 
  214. alloziert dann Speicher für den Entry-RECORD und den Text (einschließ-
  215. lich abschließender Null), kopiert den Text in den neuen Speicher und 
  216. initialisiert den Entry-RECORD. Dabei wird die Länge des Textes (ohne 
  217. Null) im Feld node.pri abgelegt. Will man Einträge anders als mit 
  218. MakeEntry erzeugen, so ist es wichtig, dies ebenfalls zu tun, da die 
  219. Länge für die weitere Verwaltung der Liste nötig ist.
  220. Die Felder userFlags und userData werden nicht benutzt und können vom 
  221. Programmierer für beliebige Zwecke verwendet werden.
  222. Ist nicht mehr genügend freier Speicher vorhanden, wird NIL zurückgegeben.
  223.  
  224. MakeExtEntry
  225. ------------
  226. Mit MakeExtEntry kann ein Eintrag erzeugt werden, der einen beliebigen
  227. Datentyp enthält:
  228.  
  229. TYPE    ExtEntry=RECORD
  230.            Node:MinEntry;
  231.            Data:IrgendeinTyp;
  232.                  END;
  233.  
  234. MakeExtEntry muß nur die Länge der gesammten ExtEntry-Struktur übergeben
  235. werden, damit der erforderliche Speicher alloziert werden kann.
  236.  
  237. InsertEntry
  238. -----------
  239. wird verwendet, um an der Stelle (Zeile) "Row" den Eintrag "Entry" in die
  240. Liste einzufügen. der Parameter "hidden" besagt, ob der Einfügevorgang 
  241. sichtbar (s. Konstante "showIt") oder unsichtbar (hideIt) erfolgen soll. 
  242. Dies kann wünschenswert sein, wenn mehere Einträge auf einmal eingefügt 
  243. werden sollen. Es wäre umständlich und würde eventuell zu viel Zeit 
  244. benötigen, nach jeder eingefügten Zeile die Liste neu anzuzeigen. 
  245. Stattdessen erfolgt das einfügen der Zeilen unsichtbar. Erst die letzte
  246. Zeile wird sichtbar eingefügt, womit die gesammte Veränderung sichtbar 
  247. wird. Einfügen außerhalb des gerade sichtbaren Ausschnitts der Liste 
  248. erfolgt natürlich immer unsichtbar, unabhängig vom Parameter "hidden".
  249. Wird bei "Row" ein negativer Wert oder ein Wert, der hinter dem Ende der
  250. Liste liegt, angegeben, dann wird am Ende der Liste angehängt.
  251.  
  252. RemoveEntry
  253. -----------
  254. Diese Prozedur entfernt einen Eintrag aus der Liste. "Row" bezeichnet die
  255. Nummer des zu ertfernenden Eintrags (Zeile). Der Parameter "hidden" wird 
  256. wie bei InsertEntry gehandhabt. Mit dem Parameter "mustRethink" hat es 
  257. folgendes auf sich:
  258. Wird der längste Eintrag aus der Liste entfernt, ändert sich die Gesammt-
  259. breite der Liste, und diese muß mit RethinkList neu bestimmt werden. Dies
  260. wird nicht automatisch durchgeführt, da es Fälle gibt, in denen das 
  261. Aufrufende Programm besser weiß, wann dies nötig ist und wann nicht. 
  262. Es ist zB. denkbar, daß bei einem Textverarbeitungs- programm alle Zeilen
  263. einer Seite sowieso die gleiche maximale Länge haben (DIN A4), und es 
  264. deshalb Performance-Verschwendung wäre, jedesmal RethinkList durch-
  265. zuführen. Wird also bei RemoveEntry festgestellt, daß der entfernte 
  266. Eintrag der Längste war, dann wird "mustRethink" TRUE, ansonsten bleibt
  267. es unverändert. Das bedeutet zwar, daß dieses Flag vor dem (ersten von 
  268. mehreren) Aufruf(en) gelöscht werden muß, ermöglicht aber eine Art Oder-
  269. Verknüpfung bei mehreren RemoveEntry-Aufrufen hintereinander.
  270.  
  271. GetEntry
  272. --------
  273. ermöglicht es, die Adresse des Entrys mit der Numer "Row" zu suchen. Falls
  274. der Eintrag vorhanden ist, wird ein Zeiger auf ihn zurückgegeben, 
  275. ansonsten ist das Ergebnis NIL.
  276. Es wird darauf hingewiesen, daß diese Suche unter Umständen lange dauern
  277. kann, falls der gesuchte Eintrag nicht im sichtbaren Ausschnitt liegt 
  278. (dort wird zuerst gesucht). Besonders bei sehr großen Listen (deutlich 
  279. mehr als 1000 Einträge) kann es länger dauern, weil dann die gesammte 
  280. Liste durchgegangen wird. Dies gilt im übrigen auch für Insert- und 
  281. RemoveEntry, die intern auch diese Prozedur verwenden.
  282. Ich glaube aber, daß dies kein wesentliche Nachteil ist, weil Superlists
  283. wohl meistens für weniger lange Listen verwendet werden wird.
  284.  
  285. ClickRow
  286. --------
  287. Mit dieser Prozedur kann festgestellt werden, welchen Eintrag der 
  288. Benutzer gemeint hat, als er einen Punkt im Window der Liste angeklickt 
  289. hat. Es werden die Koordinaten des Zeigers relativ zum Nullpunkt des 
  290. RastPorts (des Windows oder Requesters) übergeben. Das Ergebnis ist dann
  291. die Nummer des Eintrags oder -1, falls sich der Mauszeiger außerhalb des
  292. Anzeigebereichs der Liste befand.
  293.  
  294. GetProp
  295. -------
  296. Wenn festgestellt worden ist, daß der Benutzer eines der Proportional-
  297. gadgets bewegt hat, muß die Stellung der Gadgets ausgelesen und der 
  298. gewünschte Ausschnitt der Liste dargestellt werden. GetProp erledigt 
  299. ersteres, RefreshList letzteres. Die beiden Prozeduren wurden nicht zu 
  300. einer zusammengefaßt, weil es möglich ist, daß der Programmierer 
  301. zwischen beiden noch einiges ausführen möchte. Bei der Verwendung von 
  302. Proportionalgadgets können nämlich Rundungsfehler auftreten, die sich 
  303. darin äußern, daß beim Vor- oder Zurückblättern um eine Seite (Anklicken
  304. der Fläche neben dem Knob im Container) eine Zeile irrtümlicherweise 
  305. übersprungen wird. So ist es möglich, vor RefreshList die Parameter des 
  306. List-RECORDS entsprechend zu korrigieren (RethinkList nicht vergessen).
  307. Wird darauf verzichtet, ist RethinkList nicht notwendig, dh. RefreshList
  308. kann direkt nach GetProp aufgerufen werden.
  309.  
  310. SetProp
  311. -------
  312. Hat sich die Größe der Liste oder des Windows verändert, oder wurde mit
  313. ScrollList gearbeitet, dann müssen Stellung (Pot) und Größe (Body) der
  314. (Auto-)Knobs der Proportionalgadgets aktualisiert werden. Dies kann mit
  315. der Prozedur SetProp geschehen, die die Pot- und Body-Variablen der 
  316. Gadgets entsprechend dem Verhältnis der sichtbaren Daten zu den 
  317. Gesammtdaten einstellt und danach Intuition.ModifyProp() aufruft. Sind 
  318. weniger Einträge vorhanden, als das Window hoch ist bzw. alle Einträge 
  319. kürzer sind als das Window breit ist, so werden die Body-Werte der 
  320. zugehörigen Gadgets auf das Maximum gestellt, dh. der Knob füllt den 
  321. ganzen Container.
  322.  
  323. ClearList
  324. ---------
  325. Diese Prozedur entfernt alle Einträge aus einer Liste und gibt den
  326. verwendeten Speicher zurück.
  327. Es ist wichtig, das alle Einträge mit MakeEntry() oder MakeExtEntry()
  328. erzeugt wurden. Sonst können Fehler beim deallozieren des Speichers
  329. auftreten.
  330.  
  331. AllocProc/DeallocProc
  332. ---------------------
  333. Mit diesen Prozedurvariablen können Speicherverwaltungsroutinen eingestellt
  334. werden.
  335.  
  336. Beispiel:
  337.  
  338. AllocProc:=Heap.Allocate;
  339. DeallocProc:=Heap.Deallocate;
  340.  
  341. oder
  342.  
  343. AllocProc:=MemSystem.Allocate;
  344. DeallocProc:=MemSystem.Deallocate;
  345.  
  346.  
  347. -------------------
  348. Viel Spaß !
  349. Bene
  350.